/*
 *  +----------------------------------------------------------------------
 *  | sophon [ A FAST GAME FRAMEWORK ]
 *  +----------------------------------------------------------------------
 *  | Copyright (c) 2023-2029 All rights reserved.
 *  +----------------------------------------------------------------------
 *  | Licensed ( http:www.apache.org/licenses/LICENSE-2.0 )
 *  +----------------------------------------------------------------------
 *  | Author: jqiris <1920624985@qq.com>
 *  +----------------------------------------------------------------------
 */

use std::cell::RefCell;

use anyhow::{anyhow, Result};
use futures::executor::block_on;

use crate::{error, fatal, info};
use crate::configs::*;

use super::*;

pub type ServerCreator = Arc<dyn Fn(Server) -> Result<ServerEntity> + Send + Sync>;

#[async_trait]
pub trait IServerEntity {
    fn init(&self);
    async fn after_init(&self);
    async fn before_shutdown(&self);
    async fn shutdown(&self);
    fn server_cfg(&self) -> &Server;
}

pub type ServerEntity = Arc<dyn IServerEntity + Send + Sync>;

pub trait IServerMsgHandler {
    fn self_event_handler(&self) -> CallbackFunc {
        Arc::new(default_callback)
    }

    fn broadcast_event_handler(&self) -> CallbackFunc {
        Arc::new(default_callback)
    }
}

pub type ServerMsgHandler = Arc<dyn IServerMsgHandler + Send + Sync>;

pub struct DefaultMsgHandler {}

impl DefaultMsgHandler {
    pub fn new() -> Arc<Self> {
        Arc::new(Self {})
    }
}

impl IServerMsgHandler for DefaultMsgHandler {}

pub trait IServerPlugin {
    fn init(&self, s: &ServerBase);
    fn after_init(&self, s: &ServerBase);
    fn before_shutdown(&self, s: &ServerBase);
    fn shutdown(&self, s: &ServerBase);
}

pub type ServerPlugin = Arc<dyn IServerPlugin + Send + Sync>;

type BaseOption = Box<dyn FnMut(&mut ServerBase)>;

pub fn with_plugin(plugin: ServerPlugin) -> BaseOption {
    Box::new(move |b: &mut ServerBase| {
        b.plugins.push(plugin.clone());
    })
}

pub struct ServerBase {
    server: Server,
    rpc: ServerRpc,
    sub_builder: RssBuilder,
    plugins: Vec<ServerPlugin>,
    msg_handler: RefCell<ServerMsgHandler>,
}

impl ServerBase {
    pub fn new(server: Server, options: Option<Vec<BaseOption>>) -> Result<Self> {
        let resp = block_on(async { new_rpc_server(get_rpc_conf(), Some(server.clone())).await });
        match resp {
            Ok(rpc) => {
                let sub_builder = RssBuilder::new(server.clone());
                let mut s = Self {
                    server,
                    rpc,
                    sub_builder,
                    plugins: Default::default(),
                    msg_handler: RefCell::new(DefaultMsgHandler::new()),
                };
                if let Some(mut ops) = options {
                    for option in ops.iter_mut() {
                        option(&mut s);
                    }
                }
                Ok(s)
            }
            Err(err) => Err(anyhow!(err.to_string())),
        }
    }
    pub fn set_msg_handler(&self, handler: ServerMsgHandler) {
        self.msg_handler.replace(handler);
    }
    pub fn add_plugin(&mut self, plugin: ServerPlugin) {
        self.plugins.push(plugin);
    }
}

#[async_trait]
impl IServerEntity for ServerBase {
    fn init(&self) {
        //加载插件
        for plugin in &self.plugins {
            plugin.init(&self)
        }
        info!(
            "init the service,type:{},id:{}",
            self.server.server_type, self.server.server_id
        );
    }

    async fn after_init(&self) {
        //监控自响应事件
        let mut event_self = self.sub_builder.build();
        let msg_handler = self.msg_handler.borrow().clone();
        event_self.set_callback(msg_handler.self_event_handler());
        if let Err(err) = self.rpc.subscribe(event_self) {
            fatal!("subscribe self event error: {}", err);
        }
        //监控广播事件
        let mut event_broadcast = self.sub_builder.build();
        event_broadcast.set_callback(msg_handler.broadcast_event_handler());
        if let Err(err) = self.rpc.subscribe_broadcast(event_broadcast) {
            fatal!("subscribe broadcast event error: {}", err);
        }
        //插件处理
        for plugin in &self.plugins {
            plugin.after_init(&self)
        }
        //服务注册
        if let Err(err) = register(&self.server).await {
            fatal!("register server error: {}", err);
        }
    }

    async fn before_shutdown(&self) {
        //服务卸载
        if let Err(err) = un_register(&self.server).await {
            fatal!("un register server error: {}", err);
        }
        //插件处理
        for plugin in &self.plugins {
            plugin.before_shutdown(&self)
        }
    }

    async fn shutdown(&self) {
        //插件处理
        for plugin in &self.plugins {
            plugin.shutdown(&self)
        }
        //关闭rpc连接
        if let Err(err) = self.rpc.close() {
            error!("shutdown rpc failed: {}", err);
        }
        info!(
            "shutdown the service,type:{},id:{}",
            self.server.server_type, self.server.server_id
        );
    }

    fn server_cfg(&self) -> &Server {
        &self.server
    }
}

unsafe impl Sync for ServerBase {}

unsafe impl Send for ServerBase {}
